<?php

namespace App\Http\Services\Api\V1\App\Product;

use App\Http\Requests\Order\ReturnProductIndexRequest;
use App\Http\Requests\Order\ReturnProductStoreRequest;
use App\Models\Currency;
use App\Models\Customers\Customer;
use App\Models\Order\Order;
use App\Models\Order\OrderProduct;
use App\Models\Order\OrderStatus;
use App\Models\Products\Product;
use App\Models\ReturnProduct\ReturnAction;
use App\Models\ReturnProduct\ReturnHistory;
use App\Models\ReturnProduct\ReturnProduct;
use App\Models\ReturnProduct\ReturnReason;
use App\Models\ReturnProduct\ReturnStatus;
use App\Services\Locale\Language;
use App\Services\MobileApp\AppEnv;
use App\Services\Utils\ApiChecker;
use App\Services\Utils\Guard;
use App\Services\Utils\Transaction;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;

class AfterSaleService
{
    use ApiChecker;


    /**
     * @param ReturnProductIndexRequest $request
     * @param Customer $customer
     * @return LengthAwarePaginator
     * @throws \Exception
     */
    public function getReturnData(ReturnProductIndexRequest $request, Customer $customer)
    {
        $store_id = $customer->store_id;

        /** @var LengthAwarePaginator $returns */
        $returns = $customer->returnProducts()
            ->with('orderProducts.product',
                'orderProducts.orderOptions',
                'returnHistories.returnStatus',
                'order', 'returnStatus', 'returnReason'
                )
            ->latest('date_added')
            ->paginate($request->per_page ?: 10);

        $returns_collection = $returns->getCollection();
        /** @var Currency $currency */
        $currency = AppEnv::Currency();

        $returns_collection->transform(function(ReturnProduct $return_product) use($currency, $store_id){
           return $this->assembleReturnProductData($return_product, $currency, $store_id);
        });

        return $returns;
    }

    /**
     * @param ReturnProduct $return
     * @param $currency
     * @param $store_id
     *
     * @return array
     */
    public function assembleReturnProductData(ReturnProduct $return, $currency, $store_id)
    {
        // 产品可能被删除
        /** @var OrderProduct[]|Collection $order_products */
        $order_products = $return->orderProducts;
        $order = $return->order;

        // 有订单和订单商品
        if ($order && $order_products->count()) {
            $product_info = (new OrderService)->assembleOrderProducts($order_products, $currency, $order->currency_value)->first();
            $product_info->return_quantity = $return->quantity;

        } else {
            $product_info = [];
        }

        return [
            'return_id'          => $return->return_id,
            'trade_no'           => $return->order->trade_no ?? null,
            'return_status_name' => $return->returnStatus->name ?? null,
            'return_status_id'   => $return->returnStatus->return_status_id ?? null,
            'product_info'       => $product_info,
            'order_info'         => $this->getOrderInfo($order),
            'return_info'        => $this->getReturnInfo($return),
            'contact_info'       => $this->getContactInfo($return),
            'return_histories'   => $this->getReturnHistories($return, $store_id),
        ];
    }

    /**
     * @param ReturnProduct $return_product
     * @param $store_id
     * @return \Illuminate\Database\Eloquent\Collection
     */
    private function getReturnHistories(ReturnProduct $return_product, $store_id)
    {
        $return_histories = $return_product->returnHistories;

        $return_histories->transform(function(ReturnHistory $return_history){
            return [
                'customer_status_name' => $return_history->returnStatus->name ?? null,
                'customer_status_date' => $return_history->date_added ?? null,
                'comment'              => $return_history->comment,
            ];
        });

        $return_histories->push([
            'customer_status_name' => ReturnStatus::getReturnStatusDefaultName($store_id),
            'customer_status_date' => $return_product->date_added ?? null,
            'comment'              => $return_product->comment,
        ]);

        return $return_histories;
    }

    /**
     * @param ReturnProduct $return_product
     * @return array
     */
    private function getContactInfo(ReturnProduct $return_product)
    {
        return [
            'fullname'  => $return_product->fullname,
            'telephone' => $return_product->telephone,
        ];
    }

    /**
     * @param ReturnProduct $return_product
     * @return array
     */
    private function getReturnInfo(ReturnProduct $return_product)
    {
        return [
            'return_reason' => $return_product->returnReason->name ?? null,
            'comment'       => $return_product->comment ?? null,
            'date_added'    => $return_product->date_added ?? null,
        ];
    }

    /**
     * @param Order $order
     * @return array
     */
    private function getOrderInfo(?Order $order)
    {
        return [
            'trade_no'  => $order->trade_no ?? null,
            'date_added' => $order->date_added ?? null,
        ];
    }

    /**
     * @return mixed
     */
    public function getReturnReason()
    {
        $return_reason = (new ReturnReason)
            ->where('language_id', AppEnv::languageId())
            ->oldest('sort_order')
            ->get();

        return $return_reason;
    }

    /**
     * @return ReturnAction[]|\Illuminate\Database\Eloquent\Collection
     */
    public function getReturnAction()
    {
        $return_type = (new ReturnAction)
            ->where('language_id', AppEnv::languageId())
            ->oldest('sort_order')
            ->get();

        return $return_type;
    }

    /**
     * @return ReturnStatus[]|\Illuminate\Database\Eloquent\Collection
     */
    public function getReturnStatus()
    {
        $return_status = (new ReturnStatus)
            ->where('language_id', AppEnv::languageId())
            ->oldest('return_status_id')
            ->get();

        return $return_status;
    }

    /**
     * @param ReturnProductStoreRequest $request
     * @param $customer
     * @return array
     * @throws \Exception
     */
    public function assembleReturnData(ReturnProductStoreRequest $request, Customer $customer)
    {
        return [
            'order_id'         => $request->order_product->order_id,
            'product_id'       => $request->order_product->product_id,
            'order_product_id' => $request->order_product_id,
            'customer_id'      => $customer->customer_id,
            'fullname'         => $request->fullname ?? $customer->fullname,
            'email'            => $customer->email,
            'telephone'        => $request->telephone ?? $customer->telephone,
            'product'          => $request->product,
            'model'            => $request->model,
            'quantity'         => $request->quantity,
            'opened'           => $request->opened,
//            'return_type_id'   => $request->return_type_id,
            'return_reason_id' => $request->return_reason_id,
            'return_action_id' => $request->return_action_id,
            'return_status_id' => $request->return_status_id,
            'comment'          => $request->comment ?? '',
            'date_ordered'     => $request->date_ordered,
            'date_added'       => $request->date_added,
            'date_modified'    => $request->date_modified,
        ];
    }

    /**
     * @param $return_data
     * @return ReturnProduct|\Illuminate\Database\Eloquent\Model
     */
    public function storeReturnData($return_data)
    {
        $stored = (new ReturnProduct)->create($return_data);

        return $stored;
    }

    /**
     * @param Order $order
     * @param Customer $customer
     * @param $order_product_id
     * @throws \App\Exceptions\ApiAbstractException
     */
    public function isCanReturnProduct(?Order $order, Customer $customer, $order_product_id)
    {
        // 1.订单是否存在，客户信息是否正确。
        // 2.检查订单状态（必须是已经付款订单）。
        // 3.是否申请过售后。

        $this->checkItemExist($order);
        $this->checkIsTrue(
            ($order->customer_id === $customer->customer_id),
            trans('after_sale.order_customer_not_match')
        );

        $this->checkIsTrue(
            in_array($order->order_status_id, OrderStatus::getReturnProductOrderStatusIds()),
            trans('after_sale.order_status_can_not_apply')
        );

        $return_product = ReturnProduct::getReturnProduct($order_product_id);
        $this->checkUnless($return_product, trans('after_sale.after_sale_exist'));
    }

    /**
     * @param $return_id
     * @return mixed
     * @throws \Exception
     */
    public function cancelReturnProduct($return_id)
    {
        /** @var Customer $customer */
        $customer = Guard::customer();

        $return_product = (new ReturnProduct)->where('customer_id', $customer->customer_id)
            ->where('return_id', $return_id)
            ->where('return_status_id', '<>', ReturnStatus::RETURN_STATUS_COMPLETE)
            ->first();

        $this->checkItemExist($return_product);

        $updated = Transaction::handle(function() use($return_product){
            $updated = $return_product->update(['return_status_id' => ReturnStatus::RETURN_STATUS_COMPLETE]);
            (new ReturnHistory)->create([
                'return_id'        => $return_product->return_id,
                'return_status_id' => ReturnStatus::RETURN_STATUS_COMPLETE,
                'comment'          => '客户取消售后',
                'date_added'       => (string)Carbon::now(),
            ]);

            return $updated;
        });

        return $updated;
    }
}